home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_geomview.idb / usr / freeware / lib / geomview / maple / gvplot.mapleV3.z / gvplot.mapleV3
Encoding:
Text File  |  1999-01-26  |  26.4 KB  |  729 lines

  1. ##########################
  2. ##
  3. ##    Title   :  writeoogl,  a package for converting maple PLOT3D
  4. ##                objects to Geomview data objects.
  5. ##         gvplot,     interactive pipe to Geomview from Maple
  6. ##
  7. ##    Created :  Dec 5 1993
  8. ##
  9. ##    Authors :  Frederick Wicklin  and 
  10. ##         Stuart Levy
  11. ##               The Geometry Center
  12. ##         1300 South Second Street
  13. ##         Minneapolis, MN 55454
  14. ##
  15. ##               <fjw@geom.umn.edu>
  16. ##               <slevy@geom.umn.edu>
  17. ##
  18. ##    Documentation :   currently ?gvplot or ?writeoogl or ?geomview
  19. ##
  20. ##    History
  21. ##              fjw    9/21/93    initial maple->geomview for Maple VR2
  22. ##         slevy 11/27/93    interactive geomview pipe; 
  23. ##                backwards compatable to Maple V
  24. ##           fjw   11/29/93    debugging; added color options
  25. ##
  26. ##
  27. ##    Usage:       readlib(gvplot);
  28. ##          (optional) gvcommand := `geomview  initial-options ...`;
  29. ##          (optional) gvdirectories := `/some/dir/ectory:/other/dir...`;
  30. ##        3dplot_struct := plot3d( ... ):
  31. ##         writeoogl(`filename`, 3dplot_struct);
  32. ##        gvplot(3dplot_struct);
  33.  
  34. # To search for "geomview" and "togeomview" in directories which might not
  35. # be on the default UNIX search path, list those director(ies) here, as in
  36. #    default_gvdirectories := `/u/geom/bin:/usr/local/bin:`
  37. # or, set the "gvdirectories" variable before invoking gvplot().
  38.  
  39. default_gvdirectories := ``:
  40.  
  41. # To start geomview with non-default options, or to start another program
  42. # via gvplot, put its name and initial arguments here in place of `geomview`,
  43. # or set the variable "gvcommand" before invoking gvplot().
  44. # Changing default_gvcommand, then resaving gvplot.m, alters the default for
  45. # all users; setting the gvcommand variable changes it for just your session.
  46.  
  47. default_gvcommand := `geomview`:
  48.  
  49.  
  50. ### Upon invoking the geomview package, maple creates a global
  51. ### variable UsEr_ID__ which is assigned a "random" number.
  52. ### This variable is used to create user-specific files in /tmp.
  53. ##################################################################
  54. # There doesn't seem to be any explicit test for Maple V1 vs. V2,
  55. # but all V1 plot objects seem to begin with FUNCTION, so use that fact
  56. # to detect that we must be careful not to print invalid float constants.
  57. ##################################################################
  58. `oogl/lprn` := `oogl/lprnV2`:
  59.  
  60. writeoogl := proc()
  61.    global  `oogl/lprn`;
  62.    local header, item, ps, zlist, plist, llist, ppoint, pcolor, appear,
  63.         i, j, totl, xrange, yrange, nx, ny, oldgc,
  64.         coloron,colorlist,ccnt, totalverts;
  65.    options `Copyright 1993 by Frederick Wicklin and Stuart Levy, Geometry Center`;
  66.  
  67.    if nargs > 2 or nargs = 0 then
  68.      ERROR(`Usage:writeoogl(``filename``,3dplot_struct); OR writeoogl(3dplot_struct);`)
  69.    fi;
  70.    ps := args[nargs];
  71.    if not type(ps, PLOT3D) then ERROR(`Invalid plot structure`,ps,
  72.     `; must be of type PLOT3D, as from plot3d(), tubeplot(), spacecurve(), etc.`)
  73.    fi;
  74.    if nargs = 2 and not type(args[1], string) then
  75.     ERROR(`Invalid file name (not string)`, args[1])
  76.    fi;
  77.    if nops(ps) < 1 then ERROR(`Empty 3D plot structure!`) fi;
  78.  
  79.    ##################################################################
  80.    # When run in command-line mode, Garbage Collection (GC)         #
  81.    # messages printed to terminal can interfere with the data flow. #
  82.    # Therefore suppress GC during writing of GeomView data          #
  83.    ##################################################################
  84.    if nargs = 2 then
  85.        oldgc := status[5];      # words increment for automatic garbage collection
  86.        gc(0);            # suppress garbage collection        
  87.        print(`Saving Maple 3D structs to Geomview file`, args[1]);
  88.        writeto(args[1]);
  89.    fi;
  90.    xrange := 'xrange';        # nullify this local variable
  91.    appear := find_appearance(1, ps);
  92.    lprint( appear, `{LIST` );
  93.  
  94.    ##################################################################
  95.    ### BEGIN main loop over all 3D plots (may be a list of plots) ###
  96.    ##################################################################
  97.    for item in ps do
  98.      coloron := FALSE;        # default is no color info
  99.      header := op(0,item);
  100.  
  101.      if header = FUNCTION then
  102.     # Maple V1 only:  FUNCTION( f(x,y),  xrange, yrange )
  103.     # or    FUNCTION( x(u,v), y(u,v), z(u,v),  u = u0..u1, v = v0..v1 )
  104.     xrange := op(nops(item)-1, item);
  105.     if type(xrange, `=`) then xrange := op(2, xrange) fi;
  106.     yrange := op(nops(item), item);
  107.     if type(yrange, `=`) then yrange := op(2, yrange) fi;
  108.     # Maple V1 -- don't trust lprint()
  109.     `oogl/lprn` := `oogl/lprnV1`;
  110.  
  111.      ###########################  GRID   ############################
  112.      # EX: plot3d( f(x,y), x=xmin..xmax, y=ymin..ymax] 
  113.      # Saving Maple GRID struct to geomview ZMESH struct
  114.      # Maple V1:  FUNCTION( f(x,y), xrange,yrange ) followed by GRID( zlist )
  115.      #  In Maple V1, we might see either ZMESH-style data (only Z per vertex)
  116.      #    or a full 3-D mesh (x,y,z per vertex).  Just check the first
  117.      #    vertex to see.
  118.      # Maple V2:  GRID( xrange, yrange, zlist )
  119.      #    Maple V2 uses GRID only for ZMESH-style data,
  120.      #    and uses a MESH header for meshes with general 3-D verts.
  121.      ###############################################################
  122.      elif header = GRID then
  123.     if type(xrange, `..`) then
  124.         zlist := item
  125.     else                # this is typical VR2 route
  126.         xrange := op(1, item);
  127.         yrange := op(2, item);
  128.         zlist := op(3, item);
  129.         #######################################################
  130.         # if color, then there are 4 possibilities:
  131.         # colorlist = COLOR(HUE, h[1],...,h[nops[colorlist])
  132.         # colorlist = COLOR(HUE, h)
  133.         # colorlist = COLOR(RGB, r[1],g[1],b[1],...)
  134.         # colorlist = COLOR(RGB, r,g,b)
  135.         # Convert HUES to an RGB value using HSV2RGB and
  136.         # (assume that Maple uses s=v=1).  Add a 1 at the end of
  137.         # the list for geomview's "alpha": 0<=>transparent, 1<=>opaque
  138.         #######################################################
  139.         if( nops(item)>3 ) then 
  140.         colorlist := find_colorlist(4, item);
  141.         coloron := op(1,colorlist); # either RGB, HUE, or FALSE
  142.         fi;
  143.     fi;
  144.     nx := nops(zlist);
  145.     ny := nops(op(1,zlist));
  146.     if type(op(1, op(1,zlist)), list) then
  147.         lprint(`{ { MESH`, ny, nx)
  148.     else   # scale this data by wrapping it in transformation matrix
  149.         lprint(`{ INST transform { `);    
  150.         `oogl/lprn`( [0, (op(2,yrange)-op(1,yrange)) / (ny-1), 0, 0] );
  151.         `oogl/lprn`( [(op(2,xrange)-op(1,xrange)) / (nx-1), 0, 0, 0] );
  152.         lprint(0, 0, 1, 0);
  153.         `oogl/lprn`( [op(1,xrange), op(1,yrange), 0, 1] );
  154.         if(coloron = FALSE) then
  155.         lprint(`  } geom { ZMESH`, ny, nx);      # gv type
  156.         else
  157.         lprint(`  } geom { CZMESH`, ny, nx);      # color gv type
  158.         fi;
  159.     fi;
  160.     ccnt := 2;            # set color counter to 2
  161.     for plist in zlist do
  162.         for ppoint in plist do     
  163.            `oogl/lprn`(ppoint);
  164.            if (coloron = HUE) and nops(colorlist)>2 then 
  165.              lprint(HSV2RGB(op(ccnt,colorlist), 1,1), 1);
  166.              ccnt := ccnt + 1;
  167.            elif (coloron = HUE) and nops(colorlist)=2 then
  168.          lprint(HSV2RGB(op(2,colorlist), 1,1), 1);
  169.            elif (coloron = RGB) and nops(colorlist)>4 then 
  170.              lprint(op(ccnt,colorlist),op(ccnt+1,colorlist),op(ccnt+2,colorlist),1);
  171.              ccnt := ccnt + 3;
  172.            elif (coloron = RGB) and nops(colorlist)=4 then
  173.          lprint(op(2,colorlist),op(3,colorlist),op(4,colorlist), 1);
  174.            fi;
  175.         od;
  176.     od;
  177.     lprint( `} }`);
  178.  
  179.      ###########################  MESH   ###########################
  180.      # EX: plot3d( [x(s,t), y(s,t), z(s,t)], s=smin..smax, t=tmin..tmax] 
  181.      # Saving Maple MESH struct to geomview MESH struct
  182.      ###############################################################
  183.      elif header = MESH  then
  184.     llist := op(1, item):
  185.         if( nops(item)>1 ) then
  186.           colorlist := find_colorlist(2, item);
  187.           coloron := op(1,colorlist); # either RGB, HUE, or FALSE
  188.         fi;
  189.     if(coloron=FALSE) then 
  190.        lprint(`{ MESH ` );          # gv type
  191.     else 
  192.        lprint(`{ CMESH ` );          # color gv type
  193.     fi;
  194.     lprint( nops(llist));         # num x elements
  195.     lprint( nops(op(1,llist)) );    # num y elements
  196.     # Maple store points in row-dominant manner
  197.         # But geomview want column-dominant, so need to 
  198.     # print out the transpose of the matrix in the plot3d struct
  199.     nx := nops(llist);        # maple rows
  200.     ny := nops(op(1,llist));    # maple cols
  201.     for j from 1 to ny do
  202.       for i from 1 to nx do 
  203.         ppoint := op(j, op(i,llist));
  204.         `oogl/lprn`(ppoint);     
  205.              if (coloron = HUE) and nops(colorlist)>2 then
  206.                lprint(HSV2RGB(op((i-1)*ny+j +1,colorlist), 1,1), 1);
  207.              elif (coloron = HUE) and nops(colorlist)=2 then
  208.                lprint(HSV2RGB(op(2,colorlist), 1,1), 1);
  209.              elif (coloron = RGB) and nops(colorlist)>4 then
  210.                lprint(op(3*((i-1)*ny+j-1)+2,colorlist),op(3*((i-1)*ny+j-1)+3,colorlist),op(3*((i-1)*ny+j-1)+4,colorlist),1);
  211.              elif (coloron = RGB) and nops(colorlist)=4 then
  212.                lprint(op(2,colorlist),op(3,colorlist),op(4,colorlist), 1);
  213.              fi;
  214.       od;
  215.     od;
  216.     lprint( `}`);
  217.  
  218.      ###########################  CURVES  ##########################
  219.      # EX: spacecurve( [x(t), y(t), z(t)], t=tmin..tmax] 
  220.      # Saving Maple CURVES struct to geomview VECT struct
  221.      ###############################################################
  222.      elif header = CURVES then
  223.     llist := select(type, item, list);
  224.         if( nops(item)>1 ) then
  225.           colorlist := find_colorlist(2, item);
  226.           coloron := op(1,colorlist); # either RGB, HUE, or FALSE
  227.         fi;
  228.         lprint(`{ VECT `);          # gv type
  229.             # Number of polylines, total vertices.
  230.     totalverts := sum('nops(op(i,llist))', 'i'=1..nops(llist));
  231.     lprint(nops(llist), totalverts);
  232.     if coloron=FALSE then
  233.       lprint(1);            # One color in all
  234.       lprint(seq(nops(op(i,llist)), i=1..nops(llist))); # Vertex counts
  235.       lprint(1, 0 $ 'i'=2..nops(llist));        # Color counts.
  236.     else
  237.       lprint(totalverts);        # Total number of colors, 1 per vert
  238.       lprint(seq(nops(op(i,llist)), i=1..nops(llist))); # Vertex counts
  239.       lprint(seq(nops(op(i,llist)), i=1..nops(llist))); # color per vert
  240.     fi;
  241.     for plist in llist do
  242.       for ppoint in plist do         # print all vertices
  243.         `oogl/lprn`(ppoint);     
  244.       od
  245.     od;
  246.     if coloron=FALSE then
  247.       lprint(1,1,1,1);        # color RGBA = white and opaque
  248.         elif (coloron = HUE) and nops(colorlist)>2 then
  249.       for ccnt from 2 to nops(colorlist) do
  250.         lprint(HSV2RGB(op(ccnt,colorlist), 1,1), 1);
  251.           od;
  252.         elif (coloron = HUE) and nops(colorlist)=2 then
  253.           for ccnt from 1 to nops(llist) do
  254.             lprint(HSV2RGB(op(2,colorlist), 1,1), 1);
  255.       od;
  256.         elif (coloron = RGB) and nops(colorlist)>4 then
  257.           for ccnt from 2 by 3 to nops(colorlist) do
  258.         lprint(op(ccnt,colorlist),op(ccnt+1,colorlist),op(ccnt+2,color\list),1);
  259.       od;
  260.         elif (coloron = RGB) and nops(colorlist)=4 then
  261.           for ccnt from 1 to nops(llist) do
  262.         lprint(op(2,colorlist),op(3,colorlist),op(4,colorlist),1);
  263.       od;
  264.         fi;
  265.     lprint( `}`);
  266.  
  267.      #########################  POLYGONS  ##########################
  268.      #EX:polygonplot3d([seq([seq([x(s,t),y(s,t),z(s,t)],s=smin..smax],tmin..tmax])):
  269.      # Polygons are handled differently than the other objects w/r/t
  270.      # color.  Leave color alone and let user change color using geomview.
  271.      ###############################################################
  272.      elif header = POLYGONS then
  273.     pcolor := i $ i=1..0;    # Empty sequence
  274.     totl := 0: nx := 0:     # use nx to count number of polygons
  275.     for llist in item do        # sequence of lists POLY(),COLOR(),
  276.       if type(llist,list) then
  277.         nx := nx + 1;        # number of polygons
  278.         totl := totl + nops(llist);    # compute total number of vertices
  279.       fi
  280.     od;
  281.  
  282.     lprint(find_appearance(1, item));
  283.  
  284. #    if coloron=FALSE then
  285.       lprint(`{ OFF `);          # gv type
  286. #    else 
  287. #      lprint(`{ COFF `);        # color
  288. #    fi;
  289.     lprint(totl, nx, 0);    # total verts,polygons,"edges"(not used!)
  290.     for llist in item do 
  291.       if type(llist,list) then
  292.             for ppoint in llist do    
  293.           `oogl/lprn`(ppoint);         # List of vertices
  294.         od;
  295.       fi;
  296.     od;
  297.     lprint(``);
  298.     totl := 0;
  299.     for llist in item do
  300.       if type(llist,function) 
  301.                and (op(0,llist)=COLOR or op(0,llist)=COLOUR) then
  302.         colorlist := llist;
  303.         if op(1,llist)=HUE and nops(colorlist)=2 then
  304.             pcolor := HSV2RGB(op(2,colorlist),1,1);  # use ppoint for RGB
  305.         elif op(1,llist)=RGB and nops(colorlist)=4 then
  306.         pcolor := op(2..4,colorlist);
  307.         fi;
  308.       elif type(llist,list) then
  309.          ## There are only two possibilities for POLYGONS ##
  310.          ## In both cases, it means entire polygon is same color ##
  311.          lprint( nops(llist), i $ i=totl..totl+nops(llist)-1, ` `, pcolor);
  312.          totl := totl + nops(llist);
  313.        fi;
  314.     od;
  315.     lprint( `}`);
  316.  
  317.      #########################   POINTS   ##########################
  318.      #EX:PLOT3D(POINTS([0,0,1],[1,0,0],[0,1,0]));
  319.      ###############################################################
  320.      elif header = POINTS then
  321.     lprint(`{ VECT`, nops(item), nops(item), 0);
  322.     for plist in item do lprint(`1`) od;
  323.     lprint(``);
  324.     for plist in item do lprint(`0`) od;
  325.     lprint(``);
  326.     for ppoint in item do
  327.         `oogl/lprn`(ppoint)
  328.     od;
  329.     lprint(`}`);
  330.  
  331.      ###########################  TEXT  ############################
  332.      # 3D plots using the "plots" package may include TEXT
  333.      # This is not supported
  334.      ###############################################################
  335.      elif header = TEXT then
  336.     print(` `);
  337.      fi;
  338.    od;  # END main for loop
  339.  
  340.    lprint( `}`);
  341.    if nargs = 2 then
  342.     writeto(terminal);
  343.     gc(oldgc);
  344.    fi;
  345. end:
  346.  
  347.  
  348. gvplot := proc()
  349.    global UsEr_ID__, gvcommand, default_gvcommand, gvdirectories, default_gvdirectories;
  350.    local gvname, gvcmd, gvdirs, ps, oldgc, tmp_fname;
  351.    options `Copyright 1993 by Frederick Wicklin and Stuart Levy, Geometry Center`;
  352.    ### Set up filename to use as temporary site for data.      ###
  353.    ### Take file in /tmp and postfix number which is (hopefully) ###
  354.    ### independent of users.  Eg, if user1 and user2 are both    ###
  355.    ### using writeoogl, then they will be writing to different   ###
  356.    ### files. This is UNIX specific (but so is Geomview).     ### 
  357.    if UsEr_ID__ = 'UsEr_ID__' then
  358.     UsEr_ID__ := (round( rand() * (time()+1) ) mod 9999) + 1;
  359.    fi;
  360.    tmp_fname := `Maple`.(UsEr_ID__);
  361.  
  362.    ### Let user specify, via "gvcommand" and "gvdirectories" global vars,
  363.    ### which program/args to run when invoking geomview,
  364.    ### and how to set the search path to find it and togeomview.
  365.  
  366.    if gvcommand <> 'gvcommand'
  367.     then gvcmd := gvcommand
  368.     else gvcmd := default_gvcommand
  369.    fi;
  370.    if gvdirectories <> 'gvdirectories'
  371.     then gvdirs := gvdirectories
  372.     else gvdirs := default_gvdirectories
  373.    fi;
  374.     
  375.    ps := args[nargs];
  376.    gvname := `Maple`;
  377.  
  378.    if nargs < 1 or nargs > 2 then
  379.     ERROR(`Usage: gvplot(3dplot_structure)  -or-  gvplot(``name``, 3dplot_structure)`);
  380.    fi;
  381.    if nargs > 1 then gvname := args[1] fi;
  382.    if not type( ps, PLOT3D) then 
  383.       ERROR(`Invalid plot structure`,ps,
  384.     `; must be of type PLOT3D, as from plot3d(), tubeplot(), spacecurve(), etc.`)
  385.    fi;
  386.    # start geomview reading from stdin
  387.    if system( `PATH=` . gvdirs . `:$PATH togeomview -Mcp `.tmp_fname.` `.gvcmd.`</dev/null` ) <> 0 then
  388.     ERROR(`gvplot: togeomview: Can't start a copy of geomview.  `.
  389.         `If "togeomview" or "geomview" were not found `.
  390.         `try setting the variable "gvdirectories" to the name of the directory where `.
  391.         `they're installed (or to a colon-separated list of directories).`);
  392.    fi;
  393.    oldgc := status[5];  # words increment for automatic garbage collection
  394.    gc(0);               # suppress garbage collection messages
  395.    writeto(`/tmp/geomview/`.tmp_fname);
  396.    lprint(`(geometry`, gvname);
  397.    writeoogl( ps );
  398.    lprint(`)`);
  399.    writeto(terminal);
  400.    gc(oldgc);       # return to previous garbage collection state
  401.  
  402. end:
  403.  
  404. gvcommand := proc()
  405.    global UsEr_ID__, gvcommand, default_gvcommand, gvdirectories, default_gvdirectories;
  406.    local gvname, gvcmd, gvdirs, ps, oldgc, tmp_fname;
  407.    options `Copyright 1993 by Frederick Wicklin and Stuart Levy, Geometry Center`;
  408.    ### Set up filename to use as temporary site for data.      ###
  409.    ### Take file in /tmp and postfix number which is (hopefully) ###
  410.    ### independent of users.  Eg, if user1 and user2 are both    ###
  411.    ### using writeoogl, then they will be writing to different   ###
  412.    ### files. This is UNIX specific (but so is Geomview).     ### 
  413.    if UsEr_ID__ = 'UsEr_ID__' then
  414.     UsEr_ID__ := (round( rand() * (time()+1) ) mod 9999) + 1;
  415.    fi;
  416.    tmp_fname := `Maple`.(UsEr_ID__);
  417.  
  418.    ### Let user specify, via "gvcommand" and "gvdirectories" global vars,
  419.    ### which program/args to run when invoking geomview,
  420.    ### and how to set the search path to find it and togeomview.
  421.  
  422.    if gvcommand <> 'gvcommand'
  423.     then gvcmd := gvcommand
  424.     else gvcmd := default_gvcommand
  425.    fi;
  426.    if gvdirectories <> 'gvdirectories'
  427.     then gvdirs := gvdirectories
  428.     else gvdirs := default_gvdirectories
  429.    fi;
  430.  
  431.    # start geomview reading from stdin
  432.    if system( `PATH=` . gvdirs . `:$PATH togeomview -Mcp `.tmp_fname.` `.gvcmd.`</dev/null` ) <> 0 then
  433.     ERROR(`gvplot: togeomview: Can't start a copy of geomview.  `.
  434.         `If "togeomview" or "geomview" were not found `.
  435.         `try setting the variable "gvdirectories" to the name of the directory where `.
  436.         `they're installed (or to a colon-separated list of directories).`);
  437.    fi;
  438.    oldgc := status[5];  # words increment for automatic garbage collection
  439.    gc(0);               # suppress garbage collection messages
  440.    writeto(`/tmp/geomview/`.tmp_fname);
  441.    lprint(args);
  442.    writeto(terminal);
  443.    gc(oldgc);       # return to previous garbage collection state
  444.  
  445. end:
  446.  
  447. # possible gvplot enhancements:
  448. #  allow remote display?
  449. #  Maybe use a two-step Rube Goldberg hookup with an external converter
  450. #  that directly reads lprint() format.  Likely to be faster for large objects.
  451. #  Then gvplot would read
  452. #  gvplot := proc()
  453. #    ...
  454. #    if system(`togeomview -Mcp Maple.raw  maple2oogl -togeomview -Mcp Maple`)<>0
  455. #    then ERROR(...) fi;
  456. #    writeto(`/tmp/geomview/Maple.raw`);
  457. #    lprint(`(geometry`, gvname, `<<`);
  458. #    lprint(3dplot_struct);
  459. #    lprint(`>>)`);
  460. #    writeto(terminal);
  461. #  end:
  462. # and writeoogl would read
  463. # writeoogl := proc()
  464. #    ...
  465. #    if system(cat(`togeomview -Mcp Maple.rawdata  maple2oogl -o `, fname)) <> 0
  466. #    then ERROR(...) fi;
  467. #    writeto(`/tmp/geomview/Maple.rawdata`);
  468. #    lprint(`<<', 3dplot_string, `>>');
  469. #    writeto(terminal);
  470. #  end:
  471. #
  472. # Here 'togeomview' is actually being used to start 'maple2oogl' rather
  473. # than geomview itself.  In the first case, maple2oogl -togeomview would
  474. # invoke code to start a copy of geomview.
  475.  
  476. # Help information for writeoogl
  477. `help/text/writeoogl` := TEXT(
  478. ` `,
  479. `HELP FOR: writeoogl, gvplot                        `,
  480. ` `,
  481. `CALLING SEQUENCE:                            `,
  482. `    readlib(gvplot):                        `,
  483. `    writeoogl( ``filename``, 3dplot_struct );            `,
  484. `    writeoogl( 3dplot_struct );                    `,
  485. `    gvplot( 3dplot_struct );                    `,
  486. `    gvplot( ``geomview_name``, 3dplot_struct )            `,
  487. ` `,
  488. `PARAMETERS:                                `,
  489. `    filename        the file which will contain the Geomview data    `,
  490. `    3dplot_struct    a Maple PLOT3D data structure            `,
  491. `    geomview_name    name of the object in the Geomview browser    `,
  492. ` `,
  493. `SYNOPSIS:                                 `,
  494. `    writeoogl() accepts Maple PLOT3D structures and writes files    `,
  495. `    readable by Geomview.  gvplot() converts Maple PLOT3D structures`,
  496. `    and displays them immediately using Geomview, starting a copy of`,
  497. `    Geomview if necessary.`,
  498. ``,
  499. `    Supported data types include the Maple structures MESH, GRID,    `,
  500. `    CURVES, POINTS, and POLYGONS.    `,
  501. `    See ?plot3d[structure] for more information on Maple PLOT3D types.`,
  502. ` `,
  503. `    The Maple MESH and GRID structures are translated into Geomview's`,
  504. `    MESH and ZMESH objects, respectively, Maple CURVES and POINTS`,
  505. `    become VECT objects, and Maple POLYGONS becomes an OFF object.`,
  506. ` `,
  507. `    The Maple TEXT structure is not supported. Color information is`,
  508. `    supported for all objects.`,
  509. ``,
  510. `    The form writeoogl(filename, plot_struct) writes data in OOGL`,
  511. `    (Geomview) form to the given file; writeoogl(plot) writes to the`,
  512. `    current output stream as selected by writeto().`,
  513. ``,
  514. `    gvplot() normally starts the program "geomview", with no options;`,
  515. `    to specify something else, set the variable "gvcommand", as in:`,
  516. `       gvcommand := ``/usr/local/bin/gv -wpos 200x200 -c startup.gv``;`,
  517. `    before invoking gvplot().  Also, if the programs "geomview" or`,
  518. `    "togeomview" are not on your UNIX search path, set the variable`,
  519. `       gvdirectories := ``/some/dir/ectory:/some/other/directory``;`,
  520. `    to the appropriate directory (or directories separated by colons).`,
  521. ` `,
  522. `EXAMPLES:                                `,
  523. `    readlib(gvplot):                        `,
  524. `    my_plot := plot3d(sin(x+y), x=-Pi..Pi, y=-Pi..Pi):        `,
  525. `    writeoogl( ``sinxy.mesh``, my_plot );                `,
  526. `                  Saving Maple 3D structs to Geomview file, sinxy.mesh    `,
  527. `    steiner := plot3d([ sin(2*x)*(cos(y))^2, sin(x)*sin(2*y),    `,
  528. `          cos(x)*sin(2*y)], x=-Pi..Pi, y=-Pi..Pi):            `,
  529. `    writeoogl( ``steiner.mesh``, steiner);                `,
  530. `                  Saving Maple 3D structs to Geomview file, steiner.mesh`,
  531. `    # Display it in geomview directly                `,
  532. `    gvplot( steiner );                        `,
  533. `    # load in the plots package                    `,
  534. `    with(plots):                            `,
  535. `    trefoil := spacecurve([ -2*cos(t)- 1/2*cos(5*t)+ 3*sin(2*t),    `,
  536. `              -3*cos(2*t)+ 2*sin(t)- 1/2*sin(5*t), 2*cos(3*t), t=0..2*Pi]):`,
  537. `    writeoogl( ``trefoil.vect``, trefoil);                `,
  538. `                  Saving Maple 3D structs to Geomview file, trefoil.vect`,
  539. `    tetrahedra := [[1,0,0],[-1,0,0],[0,0,1]], [[1,0,0],[0,0,1],[0,1,0]], `,
  540. `                  [[0,1,0],[-1,0,0],[0,0,1]], [[1,0,0],[0,1,0],[-1,0,0]]:`,
  541. `    Tplot :=polygonplot3d([tetrahedra]):                `,
  542. `    writeoogl( ``tetrahedra.off``, Tplot);                `,
  543. `                  Saving Maple 3D structs to Geomview file, tetrahedra.off`,
  544. `    # you can even create a single file with multiple objects    `,
  545. `    all_objs := display3d( {my_plot, steiner, trefoil, Tplot} ):    `,
  546. `    writeoogl( ``all.list``, all_objs );                `,
  547. `                  Saving Maple 3D structs to Geomview file, all.list    `,
  548. ` `,
  549. `SEE ALSO: plot3d[structure]                        `
  550.  
  551. ):
  552.  
  553. `help/text/gvplot`   := `help/text/writeoogl`:
  554. `help/text/geomview` := `help/text/writeoogl`:
  555.  
  556.  
  557. # Convert number to string, avoiding excess digits and avoiding Maple V1's
  558. # propensity to emit Float(mantissa,exponent) rather than ordinary exponential
  559. # notation!
  560.  
  561. `oogl/cvs` := proc(v)
  562.     local sign, absmant;
  563.     options `Copyright 1993 by Stuart Levy, Geometry Center`;
  564.     if type(v, float) then
  565.         absmant := cat(abs(op(1,v)));
  566.         sign := substring(`-`, 1..1-signum(v));
  567.         if abs(v) >= 1 then
  568.         if(op(2,v) >= 0) then
  569.             cat(op(1,v), '0' $ op(2,v))
  570.         else
  571.             cat(
  572.             sign,
  573.             substring(absmant, 1..length(absmant)+op(2,v)),
  574.             `.`,
  575.             substring(absmant, length(absmant)+op(2,v)+1..8)
  576.             )
  577.         fi
  578.         elif abs(v) > .000001  then
  579.         cat( sign,
  580.             substring( `.0000000`, 1 .. 1-length(absmant)-op(2,v) ),
  581.             substring(absmant, 1..7)
  582.         )
  583.         else
  584.         cat( sign,
  585.             `.`, substring( absmant, 1..7),
  586.             `e`, op(2,v) + length(absmant)
  587.         )
  588.         fi
  589.     elif type(v, realcons) then
  590.         cat(v)
  591.     fi;
  592. end:
  593.  
  594. #
  595. # lprint a number, or a list of numbers.
  596. #
  597. `oogl/lprnV1` := proc (v)
  598.     local i;
  599.     options `Copyright 1993 by Stuart Levy, Geometry Center`;
  600.     if type(v, list) then
  601.         lprint( ' `oogl/cvs`(v[i]) ' $ i=1..nops(v) );
  602.     elif type(v,float) and abs(v) <= .1 then
  603.         lprint(`oogl/cvs`(v));
  604.     elif type(v, realcons) then
  605.         lprint(v);
  606.     else
  607.         lprint(`0 #`);
  608.     fi;
  609. end:
  610.  
  611.  
  612. # Ditto, but assume we're Maple V2, which prints floating constants
  613. # in acceptable form.  Don't bother to reformat them.
  614.  
  615. `oogl/lprnV2` := proc(v)
  616.     local i;
  617.     options `Copyright 1993 by Stuart Levy, Geometry Center`;
  618.     if type(v, list) then
  619.         lprint( 'v[i]' $ i = 1..nops(v) );    # Print on one line
  620.     elif type(v, realcons) then
  621.         lprint(v);
  622.     else
  623.         lprint(`0 #`);
  624.     fi
  625. end:
  626.  
  627. ###############################################################
  628. ## HSV2RGB converts Maple Hues to RGB colors.
  629. ## The HUEs used are in [0,1] so assume that S=V=1 (this is close)
  630. ## The following algorithm is from Computer Graphics
  631. ## By Foley, vanDam, Feiner, Hughes, 2nd Ed. Addison-Wesley
  632. ## p 593
  633. ##
  634. ## Adapted by fjw 11/29/93
  635. ## Input: (h,s,v) in [0,1]^3
  636. ## Output: sequence r,b,g  each in [0,1]
  637. ###############################################################
  638. HSV2RGB := proc( h,s,v )
  639.   local hh,ip,fp,p,q,t;
  640.   options `Copyright 1990 by Foley, vanDam, Feiner, Hughes`;
  641.   if (s = 0) then     # color on B/W center line
  642.     if (h<0) then     # There is no hue,ie, hue undefined
  643.       RETURN( v,v,v );
  644.     else
  645.       ERROR(`Undefined color`);
  646.     fi;
  647.   else
  648.     if (h>1) then hh:=1 fi;
  649.     hh := 6*h;         # hh now in [0,6]
  650.     ip := floor(hh);   # ip is integer part of h
  651.     fp := hh - ip;     # fp is fractional part of h
  652.     p  := v*(1-s); 
  653.     q  := v*(1-(s*fp));
  654.     t  := v*(1-(s*(1-fp)));
  655.     if (ip=0) then 
  656.     RETURN( v,t,p );
  657.     elif (ip=1) then
  658.         RETURN( q,v,p );
  659.     elif (ip=2) then
  660.     RETURN( p,v,t );
  661.     elif (ip=3) then
  662.     RETURN( p,q,v );
  663.     elif (ip=4) then
  664.     RETURN( t,p,v );
  665.     else 
  666.     RETURN( v,p,q );
  667.     fi;
  668.   fi;
  669. end:
  670.  
  671.  
  672. ########################################################
  673. # find_colorlist
  674. # input: n       where to start looking for color data
  675. #        item    what list to search
  676. # output: list of color information or NULL list
  677. ########################################################
  678. find_colorlist := proc(n,item)
  679.   local i;    
  680.   options `Copyright 1993 by Frederick Wicklin, Geometry Center`;
  681.   for i from n to nops(item) do
  682.      if type(op(i,item),function) and (op(0,op(i,item))=COLOR or op(0,op(i,item))=COLOUR) then
  683.        RETURN(op(i,item))
  684.     fi;
  685.   od;
  686.   RETURN([FALSE]);  # no color info found
  687. end:
  688.  
  689. ########################################################
  690. # find_appearance
  691. # input: n    index to start seeking color data
  692. #     list    list to search
  693. # output: argument of STYLE option (e.g. `PATCH`) or [] list.
  694. ########################################################
  695. find_appearance := proc(n, list)
  696.   local i, part, ap, color, colortype;
  697.   ap := ``; color := ``;
  698.   for i from n to nops(list) do
  699.     part := op(i,list);
  700.     if type(part,function) and (op(0,part)=COLOR or op(0,part)=COLOUR) then
  701.     colortype := op(1,part);
  702.     if colortype = HUE and nops(part) = 2 then
  703.       color := [HSV2RGB(op(2,part), 1, 1)]
  704.     elif colortype = RGB and nops(part) = 4 then
  705.       color := [op(2..4,part)]
  706.     fi
  707.     # Otherwise, this "color" tag isn't for us
  708.     elif type(part,function) and op(0,part) = STYLE then
  709.     if op(1,part) = PATCH then
  710.        ap := cat(ap, ` +face -edge`)
  711.     elif op(1,part) = LINE or op(1,part) = WIREFRAME then
  712.        ap := cat(ap, ` -face +edge`)
  713.     fi
  714.     elif type(part,function) and op(0,part) = THICKNESS and type(op(1,part),integer) then
  715.     ap := cat(ap, ` linewidth `, op(1,part));
  716.     fi
  717.   od;
  718.   if color <> `` then
  719.     color := cat( op(1..3, map(v -> cat(convert(v,string),` `), color) ) );
  720.     ap := cat(ap, `\n material { edgecolor `, color, `\n  diffuse `, color, `}\n`);
  721.   fi;
  722.   if ap <> `` then
  723.     ap := cat(` appearance { `, ap, `}`)
  724.   fi;
  725.   RETURN(ap);
  726. end:
  727.  
  728. [`writeoogl`, `gvplot`];
  729.